#include "Shader.h"
#include "../Common/ZException.h"

GLOBAL_NAMESPACE_BEGIN

#ifdef RENDER_OPENGL

//GLShader defaultVertexShader    = GLShader(SHADER_GL_Vertex);
//GLShader defaultFragmentShader  = GLShader(SHADER_GL_Fragment);
//GLShader defaultGeometryShader  = GLShader(SHADER_GL_Geometry);

GLShader::GLShader(const GLShaderType& type)
    : shader_(NULL)
    , type_(type)
{
    //static_init();
}

GLShader::GLShader(const GLShaderType& type, const char* shaderSrc, const char* shaderName)
    : shader_(NULL)
    , shaderName_(shaderName)
    , shaderSrc_(shaderSrc_)
    , type_(type)
{
    //init();
}

GLShader::~GLShader()
{
    destroy();
}

void GLShader::init()
{
    shader_ = new QGLShader(QGLShader::ShaderType(type_));
    shader_->compileSourceFile(QString(shaderName_.c_str()));
}

void GLShader::bind(QWidget* parent)
{
    init();
}

void GLShader::destroy()
{
    if (shader_)
        delete shader_;
    shader_ = NULL;
}

void GLShader::static_init()
{
    switch (type_)
    {
    case SHADER_GL_Vertex:
        shaderName_ = std::string("Default Veretx Shader");
        createDefaultVertexShader();
        break;
    case SHADER_GL_Fragment:
        shaderName_ = std::string("Default Fragment Shader");
        createDefaultFragmentShader();
        break;
    case SHADER_GL_Geometry:
        shaderName_ = std::string("Default Geometry Shader");
        createDefaultGeometryShader();
        break;
    default:
        break;
    }
}

void GLShader::createDefaultVertexShader()
{
    const char *vsrc =
        "uniform mat4 u_MVPMatrix;\n"
        "attribute vec4 a_Position;\n"
        "attribute vec4 a_Color;\n"
        "varying vec4 v_Color;\n"
        "void main() \n"
        "{ \n"
        "     v_Color = a_Color;\n"
        "     gl_Position = u_MVPMatrix * a_Position; \n"
        "}\n";

    shader_ = new QGLShader(QGLShader::ShaderType(type_));
    shader_->compileSourceCode(vsrc);
}

void GLShader::createDefaultFragmentShader()
{
    const char *fsrc =
        "varying vec4 v_Color;     \n"
        "void main(void)\n"
        "{\n"
        "    gl_FragColor = v_Color;\n"
        "}\n";

    shader_ = new QGLShader(QGLShader::ShaderType(type_));
    shader_->compileSourceCode(fsrc);
}

void GLShader::createDefaultGeometryShader()
{
    // unfinished
    ZFW_EXCEPTION(Exception::ERR_NOT_IMPLEMENTED, "Geometry Shader not defined.", "createDefaultGeometryShader()");
}

QGLShader* GLShader::getShader()
{
    return shader_;
}

GLShaderType GLShader::getShaderType()
{
    return type_;
}

std::string GLShader::getShaderName()
{
    return shaderName_;
}

GLShader* GLShader::getDefaultShader(const GLShaderType& type)
{
    switch (type)
    {
    case SHADER_GL_Vertex:
        return &defaultVertexShader;
    case SHADER_GL_Fragment:
        return &defaultFragmentShader;
    case SHADER_GL_Geometry:
        return &defaultGeometryShader;
    }

    return NULL;
}

#endif

GLOBAL_NAMESPACE_END